home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 23 / AACD 23.iso / AACD / Programming / tek / sock / findsockport.c < prev    next >
C/C++ Source or Header  |  2001-05-12  |  5KB  |  218 lines

  1.  
  2. /* 
  3. **    TEKlib
  4. **    (C) 2001 TEK neoscientists
  5. **    all rights reserved.
  6. **
  7. **    msgport = TFindSockPort(TAPTR task, TSTRPTR ipname, TUINT16 port, TTAGITEM *tags)
  8. **
  9. **    return proxy to a remote messageport.
  10. **
  11. **    task    - current context
  12. **    ipname    - ip name string (if TNULL, localmachine will be contacted)
  13. **    port    - port number on which the remote messageport is expected
  14. **
  15. **    tags:
  16. **        TSock_ReplyTimeout, TTIME *    
  17. **            timeout for replies. default: 10 seconds.
  18. **            by current definitions, the socket will immediately fall into
  19. **            a 'broken' state and reject further communication with a remote
  20. **            partner when a reply timeouts.
  21. */
  22.  
  23. #include "tek/sock.h"
  24. #include "tek/debug.h"
  25. #include "tek/kn/exec.h"
  26. #include "tek/kn/sock.h"
  27.  
  28. struct clientsocktaskinitdata
  29. {
  30.     TSTRPTR ipname;
  31.     TUINT16 portnr;
  32.     TTIME replytimeout;
  33. };
  34.  
  35. struct clientsocktaskdata
  36. {
  37.     knsockobj sockname;            /* remote socket name object */
  38.     TAPTR clientsocket;            /* client socket object */
  39.     TPORT *msgport;                /* msgport proxied */
  40. };
  41.  
  42. static TBOOL clientsocktaskinitfunc(TTASK *task);
  43. static TVOID clientsocktaskfunc(TTASK *task);
  44. static TINT destroyproxymsgport(TPORT *msgport);
  45.  
  46.  
  47. TPORT *TFindSockPort(TAPTR task, TSTRPTR ipname, TUINT16 portnr, TTAGITEM *tags)
  48. {
  49.     TTASK *proxytask;
  50.  
  51.     struct clientsocktaskinitdata initdata;
  52.     TTAGITEM tasktags[4];
  53.  
  54.     TTIME *replytime = (TTIME *) TGetTagValue(TSock_ReplyTimeout, TNULL, tags);
  55.  
  56.     initdata.ipname = ipname;
  57.     initdata.portnr = portnr;
  58.     
  59.     if (replytime)
  60.     {
  61.         initdata.replytimeout.sec = replytime->sec;
  62.         initdata.replytimeout.usec = replytime->usec;
  63.     }
  64.     else
  65.     {
  66.         initdata.replytimeout.sec = 32;
  67.         initdata.replytimeout.usec = 0;
  68.     }
  69.  
  70.     tasktags[0].tag = TTask_InitFunc;
  71.     tasktags[0].value = (TTAG) clientsocktaskinitfunc;
  72.     tasktags[1].tag = TTask_UserData;
  73.     tasktags[1].value = (TTAG) &initdata;
  74.     tasktags[2].tag = TTask_CreatePort;
  75.     tasktags[2].value = (TTAG) TFALSE;
  76.     tasktags[3].tag = TTAG_DONE;
  77.     
  78.     proxytask = TCreateTask(task, (TTASKFUNC) clientsocktaskfunc, tasktags);
  79.     if (proxytask)
  80.     {
  81.         TPORT *msgport = ((struct clientsocktaskdata *) proxytask->userdata)->msgport;
  82.         msgport->proxy = proxytask;
  83.         return msgport;
  84.     }
  85.  
  86.     return TNULL;
  87. }
  88.  
  89.  
  90.  
  91. static TBOOL clientsocktaskinitfunc(TTASK *task)
  92. {
  93.     struct clientsocktaskinitdata *initdata = TTaskGetData(task);
  94.     struct clientsocktaskdata *data = TTaskAlloc(task, sizeof(struct clientsocktaskdata));
  95.     if (data)
  96.     {
  97.         data->msgport = TCreatePort(task, TNULL);
  98.         if (data->msgport)
  99.         {
  100.             if (kn_initsockname(&data->sockname, initdata->ipname ? initdata->ipname : "127.0.0.1", initdata->portnr))
  101.             {
  102.                 data->clientsocket = kn_createclientsock(&task->heapmmu, &data->sockname, &task->timer, &initdata->replytimeout);
  103.                 if (data->clientsocket)
  104.                 {
  105.                     /*    overwrite msgport's destructor - see annotations below */
  106.                     data->msgport->handle.destroyfunc = (TDESTROYFUNC) destroyproxymsgport;
  107.                     task->userdata = data;
  108.                     return TTRUE;
  109.                 }
  110.                 kn_destroysockname(&data->sockname);
  111.             }
  112.             TDestroy(data->msgport);
  113.         }
  114.         TTaskFree(task, data);
  115.     }
  116.     return TFALSE;
  117. }
  118.  
  119.  
  120.  
  121. /* 
  122. **    client task
  123. */
  124.  
  125. static TVOID clientsocktaskfunc(TTASK *task)
  126. {
  127.     struct clientsocktaskdata *data = task->userdata;
  128.     TMSG *msg;
  129.     TLIST pendlist;
  130.     TUINT signals;
  131.  
  132.     TInitList(&pendlist);
  133.  
  134.     do
  135.     {
  136.         kn_waitclientsock(data->clientsocket, &task->sigevent);
  137.         
  138.         while ((msg = kn_getclientsockmsg(data->clientsocket)))
  139.         {
  140.             /* reply msg to respective replyport */
  141.  
  142.             if (msg->replyport)
  143.             {
  144.                 msg->status |= TMSG_STATUS_PENDING;
  145.                 kn_lock(&msg->replyport->lock);
  146.                 TAddTail(&msg->replyport->msglist, (TNODE *) msg);
  147.                 TSignal(msg->replyport->sigtask, msg->replyport->signal);
  148.                 kn_unlock(&msg->replyport->lock);
  149.             }
  150.             else
  151.             {
  152.                 TMMUFreeHandle(msg);
  153.             }
  154.         }
  155.  
  156.         while ((msg = (TMSG *) TRemHead(&pendlist)))
  157.         {
  158.             if (!kn_putclientsockmsg(data->clientsocket, msg))
  159.             {
  160.                 TAddHead(&pendlist, (TNODE *) msg);                /* can be sent later */
  161.                 goto cst_skip;
  162.             }
  163.         }
  164.  
  165.         while ((msg = TGetMsg(data->msgport)))
  166.         {
  167.             if (!kn_putclientsockmsg(data->clientsocket, msg - 1))
  168.             {
  169.                 TAddTail(&pendlist, (TNODE *) (msg - 1));        /* can be sent later */
  170.                 break;
  171.             }
  172.         }
  173.  
  174. cst_skip:
  175.  
  176.         signals = TSetSignal(task, 0, data->msgport->signal);
  177.  
  178.     } while (!(signals & TTASK_SIG_ABORT));
  179.  
  180.  
  181.     if (!TListEmpty(&pendlist))
  182.     {
  183.         tdbprintf(10, "*** clientsocktaskfunc: shutting down proxy - warning: pendlist not empty\n");
  184.     }
  185.  
  186.     kn_destroyclientsock(data->clientsocket);
  187.     kn_destroysockname(&data->sockname);
  188.  
  189.     TDestroy(data->msgport);        /* actually destroy the msgport, this time with its regular destructor */
  190.  
  191.     TTaskFree(task, data);            /* not really needed - task allocations will be freed on task exit */
  192. }
  193.  
  194.  
  195.  
  196. static TINT destroyproxymsgport(TPORT *msgport)
  197. {
  198.     /*
  199.     **    this will cause this msgport to be deleted, because
  200.     **    it's owned by its proxy. so deleting the proxy
  201.     **    will destroy this messageport as well.
  202.     */
  203.  
  204.     TAPTR proxy = msgport->proxy;
  205.  
  206.     tdbprintf(2,"*** destroyproxymsgport: enter\n");
  207.  
  208.     msgport->proxy = TNULL;
  209.     msgport->handle.destroyfunc = (TDESTROYFUNC) TDestroyPort;    /* overwrite with regular destructor */
  210.     TSignal(proxy, TTASK_SIG_ABORT);
  211.     TDestroy(proxy);
  212.  
  213.     tdbprintf(2,"*** destroyproxymsgport: done\n");
  214.  
  215.     return 0;
  216. }
  217.  
  218.